/**
 * Author:George
 * Description:
 * System to handle main flow of the program, getting command 
 * and responds information to user. provide function such as
 * "Add Order","Remove Order","display status"... functions.
 * 
 */
package GoldenEagle;

import java.io.File;
import java.util.ArrayList;
import java.util.Scanner;

import javax.swing.JFileChooser;

public class MenuSystem {
	private ArrayList<Order> arrExistOrders;
	private ArrayList<Bill> arrPayedBills;
	private Menu menu;
	private String strIntroduction;
	private String[] strHelpMsg;
	private String[] strInstruction;
	
	private int maxTable;

	private Scanner in = new Scanner(System.in);

	public MenuSystem(boolean useDefalutPath) {

		arrExistOrders = new ArrayList<Order>();
		arrPayedBills = new ArrayList<Bill>();
		if (useDefalutPath) {
			menu = new Menu(new File(Menu.getDefaultMenuFilePath()));
		} else {
			JFileChooser fc = new JFileChooser();
			fc.showOpenDialog(null);
			menu = new Menu(fc.getSelectedFile());
		}

		strIntroduction = DataProvider.getData("Introduction");
		strHelpMsg = DataProvider.getData("HelpMsg").split(">");
		strInstruction = DataProvider.getData("Instruction").split(">");
		
		maxTable = Integer.parseInt(DataProvider.getData("Max Table"));

	}

	/**
	 * not for outer use
	 */
	private MenuSystem() {
	}

	public int getOrderCount() {
		return arrExistOrders.size();
	}

	public int getBillCount() {
		return arrPayedBills.size();
	}

	/**
	 * return null if the table is not attach with order(table is empty)
	 * 
	 * @param table
	 * @return the query of order
	 */
	public Order getOrderWithTable(int table) {
		for (int i = 0; i < arrExistOrders.size(); i++) {
			Order o = arrExistOrders.get(i);
			if (o.getTable() == table) {
				return o;
			}
		}
		return null;
	}

	/**
	 * Add Order to system with command Format
	 * 
	 * @param splitCmd
	 * @return
	 */
	public Order addOrder(String[] splitCmd) {
		try {

			int iTable = Integer.parseInt(splitCmd[1]);

			// check if the order exist in specified table(assume one table has
			// only one order)
			Order order = getOrderWithTable(iTable);
			boolean isOrderExist = order != null;

			// if the table is empty, than create a new order
			if (!isOrderExist) {
				int numCustomer = Integer.parseInt(splitCmd[2]);
				String staffName = splitCmd[3];
				order = new Order(iTable, numCustomer, staffName);
				arrExistOrders.add(order);
				System.out.println("Order Added");
			}

			// if order exist, than skip the numCustomer and staffName input.
			for (int i = isOrderExist ? 2 : 4; i < splitCmd.length; i++) {
				MenuSubject ms = menu.getMenuSubject(Integer
						.parseInt(splitCmd[i]));
				order.add(ms);
			}

			return order;
		} catch (Exception e) {
			System.out
					.println("Wrong format:[2]-[table.no]-[numCustomer]-[staffName]");
		}
		return null;
	}

	public void removeOrder(int table) {
		Order o = getOrderWithTable(table);
		if (o != null)
			arrExistOrders.remove(o);
	}

	public void removeOrder(String[] splitCmd) {
		try {
			int table = Integer.parseInt(splitCmd[1]);
			removeOrder(table);
		} catch (NumberFormatException e) {
			System.out.println("Wrong format:[3]-[index of order to remove]");
		} catch (IndexOutOfBoundsException e2) {
			System.out.println("order not exist.");
		}
	}

	public void billing(String[] splitCmd) {
		try {
			int table = Integer.parseInt(splitCmd[1]);
			Order toBillOrder = getOrderWithTable(table);

			// create a bill from order
			Bill bill = new Bill(toBillOrder);

			arrPayedBills.add(bill);
			arrExistOrders.remove(toBillOrder);
			bill.display();
		} catch (IndexOutOfBoundsException e) {
			System.out.println("Wrong format:[4]-[Order Table No.]");
		}

	}

	private void displayTableStatus(String[] splitCmd) {
		Table table = new Table(arrExistOrders);
		table.display();
	}

	private boolean confirmExit() {
		System.out.println("Sure Exit the system? Y/N");
		// if input Y then exit the program
		return in.next().equalsIgnoreCase("Y");
	}

	public boolean run() {
		printMsg(strInstruction);
		Option cmdOption;
		String cmd = "";
		String[] splitCmd;
		while (true) {

			cmd = in.next();
			splitCmd = cmd.split("-");
			cmdOption = Option.getOption(splitCmd);
			// the use of number string is for preventing bug which
			// may caused by inputing other (char) type data
			// that implicitly convert to integer
			switch (cmdOption) {
			case DisplayTable:
				displayTableStatus(splitCmd);
				break;
			case AddOrder:
				addOrder(splitCmd);
				break;
			case RemoveOrder:
				removeOrder(splitCmd);
				break;
			case Billing:
				billing(splitCmd);
				break;
			case DisplayRecord:
				displayRecord("Existed Order:","(No Exist Order)",arrExistOrders);
				displayRecord("\nPayed Bill:","(No Payed Bill)",arrPayedBills);
				break;
			case PrintMenu:
				menu.getMenuList(true);
				break;
			case PrintHelp:
				printMsg(strHelpMsg);
				break;
			case Empty:
				confirmExit();
				break;
			default:
				return false;
			}
		}

	}

	private void displayRecord(String title,String warning,ArrayList<? extends Displayable> list) {
		
		System.out.println(title);
		if (list.size() == 0) {
			System.out.println(warning);
		} else {
			for (int i = 0; i < list.size(); i++) {
				list.get(i).display();
			}
		}
		
	}

	private void printMsg(String[] msg) {
		for(int i = 0;i<msg.length;i++)
			System.out.println(msg[i]);
		
	}


}
